
#include <stdlib.h>
#include <stdio.h>
#include "eval-upmc.h"
#include "y.tab.h"


//#define SIZE_STACK 100

void free_ast(ast_st* a) {
    switch(a->op) {
        case Entier:
        case Reel:
            free(a);
            break;
        case Plus:
        case Moins:
        case Fois:
        case Divise:
        case Puissance:
        case Neg:
            free_ast(a->childs.left);
            free_ast(a->childs.right);
            free(a);
            break;
        default: break;
    }
}


/* new integer node */
ast_st* create_integer(int value) {
    ast_st *a;
    a = (ast_st*) malloc(sizeof(ast_st));
    if (a == NULL) {
        exit(1);
    }
    a->num = value;
    a->op = Entier;
    return a;
}

/* new real number node */
ast_st* create_real(double value) {
    ast_st *a;
    a = (ast_st*) malloc(sizeof(ast_st));
    if (a == NULL) {
        exit(1);
    }
    a->flo = value;
    a->op = Reel;
    return a;
}

/* new ast with the given operation, left child and right child */
ast_st* create_node(kind_op op, ast_st* left, ast_st* right) {
    ast_st *a;
    a = (ast_st*) malloc(sizeof(ast_st));
    if (a == NULL) {
        free_ast(left);
        free_ast(right);
        exit(1);
    }
    a->childs.left = left;
    a->childs.right = right;
    a->op = op;
    return a;
}

double eval(ast_st* ast) {
    double left, right;
    switch (ast->op) {
        case Reel:
            return ast->flo;
            break;
        case Entier:
            return (double) ast->num;
            break;
        case Plus:
            left = eval(ast->childs.left);
            right = eval(ast->childs.right);
            return left + right;
            break;
        case Moins:
            left = eval(ast->childs.left);
            right = eval(ast->childs.right);
            return left - right;
            break;
        case Fois:
            left = eval(ast->childs.left);
            right = eval(ast->childs.right);
            return left * right;
            break;
        case Divise:
            left = eval(ast->childs.left);
            right = eval(ast->childs.right);
            if (right == 0) {
                printf("Division by zero\n");
            }
            return left / right;
            break;
        case Neg:
            left = eval(ast->childs.left);
            right = eval(ast->childs.right);
            return left != right;
            break;
        case Puissance:
            left = eval(ast->childs.left);
            right = eval(ast->childs.right);
            return pow(left, right);
            break;
        default:
            return 0.;
            break;
    }
}

int parseArithmetic (const char * arith) {
    
    ast_st* result;
    int val = 0;
    
    yy_scan_string(arith);
    yylex();
    result = yyparse();
    
    val = eval(result);
    
    free_ast(result);
    yylex_destroy();
    
    
    return val;
}

